package com.xxl.job.consume.service;

import com.xxl.job.consume.model.AlarmDefModel;
import com.xxl.job.consume.model.AlarmInfoModel;
import com.xxl.job.consume.model.DeviceDefModel;
import com.xxl.job.consume.model.EsInfoModel;
import com.xxl.job.consume.repository.*;
import com.xxl.job.consume.utils.DateUtil;
import com.xxl.job.consume.utils.SequenceUtils;
import com.xxl.job.consume.utils.ThreadLocalDateUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 报警判断
 */
@Service
public class AlarmJudgeService {

    @Autowired
    private AlarmInfoRepository alarmInfoRepository;
    
    @Autowired
    private AlarmDefRepository alarmDefRepository;
    
    @Autowired
    private DeviceDefRepository deviceDefRepository;

    @Autowired
    private EsInfoRepository esInfoRepository;

    @Autowired
    private RedisSequenceService cacheService;

    @Autowired
    private BkJsonDataService bkJsonDataService;

    @Resource
    private AlarmInfoDao alarmInfoDao;


    /**
     * 判断是否产生告警信息
     * @param actVal 实时值
     * @param defAlarmModel
     * @return
     */
    public boolean checkIsAlarm(String actVal,AlarmDefModel defAlarmModel) {
        String sJudCls = defAlarmModel.getJudcls(); //判断符号
        String fJudVal=defAlarmModel.getJudval();//比较值

        double dfJudVal=0.0;
        String maxfJudVal="0";
        String minfJudVal="0";
        if("6".equals(sJudCls)||"7".equals(sJudCls)){//甲烷
            minfJudVal=fJudVal.substring(0,fJudVal.indexOf("&"));
            maxfJudVal=fJudVal.substring(fJudVal.indexOf("&")+1);
        }else{
            dfJudVal=Double.parseDouble(fJudVal);
        }

        double dmaxfJudVal=Double.parseDouble(maxfJudVal);
        double dminfJudVal=Double.parseDouble(minfJudVal);

        double dactVal=Double.parseDouble(actVal);
        if ("1".equals(sJudCls)){//'1.=；2.>；3.<；4.>=；5.<=；6.<<；7.<= <='
            if (fJudVal.equals(actVal)) return  true;
        }
        if("2".equals(sJudCls)){
            if(dactVal>dfJudVal) return true;
        }
        if("3".equals(sJudCls)){
            if(dactVal<dfJudVal) return true;
        }
        if("4".equals(sJudCls)){
            if(dactVal>=dfJudVal) return true;
        }
        if("5".equals(sJudCls)){
            if(dactVal<=dfJudVal) return true;
        }
        if("6".equals(sJudCls)){
            if(dminfJudVal<dactVal&&dactVal<dmaxfJudVal) return true;
        }
        if("7".equals(sJudCls)){
            if(dminfJudVal<=dactVal&&dactVal<=dmaxfJudVal) return true;
        }
        return  false;

    }


    /**
     * 报警写入
     * @param message
     */
    public void judgeSave(AlarmInfoModel message) {//alarmUniqueId主键，almid 实时报警恢复报警成对使用，almCode关联报警信号，mergeAlarmUniqueFlag 关联实时报警主键

        AlarmInfoModel alarmInfoModel = alarmInfoRepository.query(message.getAlmCode());


        if (alarmInfoModel == null && "1".equals(message.getAlmtypeid())) {//无实时报警，写入
            String uuidUnique= getSeq();//取Redis自增序列
            message.setAlarmUniqueId(uuidUnique);
            alarmInfoDao.save(message);
            alarmInfoRepository.save(message);

            //发博坤告警
            bkJsonDataService.sendAlarmMessage(message.getSigid().substring(0,20),message.getDevname(), message.getSigid(), message.getAlmstr() , message.getFval(), "0", message.getLastEventTime());

        } else {
            if ("1".equals(message.getAlmtypeid())) {//实时报警
                //无线ap告警触发间隔10分钟
                if("104042".equals(alarmInfoModel.getDevtypeid())){
                    SimpleDateFormat simpleFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                    //判断无线ap发送kafka时机
                    try{
                        Date eventTime = simpleFormat.parse(alarmInfoModel.getLastEventTime());
                        long from = eventTime.getTime();
                        long to = new Date().getTime();
                        int minutes = (int) ((to - from) / (1000 * 60));
                        if(minutes<=10){
                            return;
                        }
                    }catch(ParseException e){}
                }

                //判断等级和时间
                if (Integer.parseInt(message.getAlmcls()) < Integer.parseInt(alarmInfoModel.getAlmcls())) {//当前等级字典小于上次等级 报警级别大于上次  上发
                    //报警升级
                    alarmInfoModel.setAlmcls(message.getAlmcls());
                }
                float iTimeDiffHour = (float)(ThreadLocalDateUtil.parse(message.getEventTime()).getTime() - ThreadLocalDateUtil.parse(alarmInfoModel.getLastEventTime()).getTime()) / (1000 * 60 * 60);

                //此处需注意报警产生频次过高带来的数据库压力问题
                if (iTimeDiffHour < 0.1 && Integer.parseInt(alarmInfoModel.getAlarmCount())>3) {//本次报警发生时间与上次报警发生时间比较小于0.1小时，并且已报警三次以上，定为频繁报警
                    //频繁报警 进行归并 增加报警次数
                    alarmInfoModel.setFreAlmFlag("1");
                    alarmInfoModel.setMergeFlag("1");
                    alarmInfoModel.setAlarmCount(String.valueOf(Integer.parseInt(alarmInfoModel.getAlarmCount())+1));
                }else{
                    //进行归并 增加报警次数
                    alarmInfoModel.setMergeFlag("1");
                    alarmInfoModel.setAlarmCount(String.valueOf(Integer.parseInt(alarmInfoModel.getAlarmCount())+1));
                }
                alarmInfoModel.setLastDalTime(message.getLastDalTime());
                alarmInfoModel.setLastEventTime(message.getLastEventTime());
                if (iTimeDiffHour >0.1 ) {//本次报警发生时间与上次报警发生时间比较大于0.1小时

                    alarmInfoDao.upgrade(alarmInfoModel);
                    alarmInfoRepository.save(alarmInfoModel);

                    //发博坤告警
                    bkJsonDataService.sendAlarmMessage(message.getSigid().substring(0,20),message.getDevname(), message.getSigid(), message.getAlmstr() , message.getFval(), "0", message.getLastEventTime());
                }

            } else {
                //判断实时报警恢复状态 未恢复 写入恢复报警 删除缓存
                if (alarmInfoModel != null && !"1".equals(alarmInfoModel.getAlarmStatus())) {

                    //写入恢复报警
                    String uuidUnique= getSeq();//取Redis自增序列
                    message.setAlarmUniqueId(uuidUnique);
                    message.setMergeAlarmUniqueFlag(alarmInfoModel.getAlarmUniqueId());
                    message.setAlmid(alarmInfoModel.getAlmid());
                    alarmInfoDao.save(message);
                    //更新恢复标记
                    alarmInfoModel.setAlarmStatus("1");
                    alarmInfoDao.frequently(alarmInfoModel);
                    alarmInfoRepository.save(alarmInfoModel);

                    //发博坤告警
                    bkJsonDataService.sendAlarmMessage(message.getSigid().substring(0,20),message.getDevname(), message.getSigid(), message.getAlmstr() , message.getFval(), "1", message.getEventTime());
                    //删除缓存
                 //  alarmInfoRepository.delete(alarmInfoModel);
                }
            }
        }
    }


    /**
     * 报警组装
     * @param devCode 设备编码
     * @param signalCode 信号编码
     * @param signalName 信号名称
     * @param gatherId 采集口id
     * @param actVal 实时值
     */
    public void alarmAssemble(String devCode,String signalCode,String signalType,String signalName ,String gatherId,String actVal,String valunit,String isSaveEs){

        List<AlarmDefModel> alarmDefModelList=alarmDefRepository.query(signalType);

        AlarmInfoModel alarmInfoModel=null;
        DeviceDefModel deviceDefModel=null;

        if (alarmDefModelList==null||alarmDefModelList.size()==0){
          //  XxlJobLogger.log("没有对应的报警信号配置，信号编码："+signalCode);
        }else {
            for(AlarmDefModel alarmDefModel:alarmDefModelList){

                boolean isAlarm=this.checkIsAlarm(actVal,alarmDefModel);

                //查询设备
                deviceDefModel = deviceDefRepository.query(devCode);

                if(deviceDefModel==null){
                //    XxlJobLogger.log("没有查询到对应的设备信息，设备编码："+devCode);
                    continue;
                }

                alarmInfoModel=new AlarmInfoModel();
                String time=ThreadLocalDateUtil.formatDate(new Date());


               // String uuidAlm= getSeq();
                String almCode = devCode+"_"+String.format("%04d", Integer.valueOf(alarmDefModel.getOrderNum()));

                if (isAlarm){
                  //  alarmInfoModel.setAlarmUniqueId(uuidUnique);
                    alarmInfoModel.setAlmid(alarmDefModel.getResId());
                    alarmInfoModel.setDevid(deviceDefModel.getDevid());
                    alarmInfoModel.setDevname(deviceDefModel.getDevname());
                    alarmInfoModel.setDevtypeid(deviceDefModel.getDevtypeid());
                    alarmInfoModel.setAlmcls(alarmDefModel.getAlmcls());
                    alarmInfoModel.setEventTime(time);
                    alarmInfoModel.setLastEventTime(time);
                    alarmInfoModel.setAlmstr(alarmDefModel.getAlmstr());
                    alarmInfoModel.setFval(actVal);
                    alarmInfoModel.setAlmCode(almCode);
                    alarmInfoModel.setSigname(signalName);
                    alarmInfoModel.setSigid(signalCode);
                    alarmInfoModel.setGatherid(gatherId);
                    alarmInfoModel.setSystemId(alarmDefModel.getAlmSystem());
                    alarmInfoModel.setAlarmCount("1");
                    alarmInfoModel.setSystemName("");
                    alarmInfoModel.setAlmtypeid("1");
                    alarmInfoModel.setAlmtypename("实时报警");
                    alarmInfoModel.setAlarmStatus("0");
                    alarmInfoModel.setSendStatus("0");
                    alarmInfoModel.setAckFlag("0");
                    alarmInfoModel.setIsAnalysis("0");
                    alarmInfoModel.setShieldStatus("0");
                    alarmInfoModel.setIsShow("0");
                    alarmInfoModel.setDisposeStatus("0");
                    alarmInfoModel.setDalTime(time);
                    alarmInfoModel.setLastDalTime(time);
                    alarmInfoModel.setSpaceid(deviceDefModel.getSpaceid());
                    alarmInfoModel.setSpecilty(valunit);
                    
                }else {
                  //  alarmInfoModel.setAlarmUniqueId(uuidUnique);
                    alarmInfoModel.setAlmid(alarmDefModel.getResId());
                    alarmInfoModel.setDevid(deviceDefModel.getDevid());
                    alarmInfoModel.setDevname(deviceDefModel.getDevname());
                    alarmInfoModel.setDevtypeid(deviceDefModel.getDevtypeid());
                    alarmInfoModel.setAlmcls(alarmDefModel.getAlmcls());
                    alarmInfoModel.setEventTime(time);
                    alarmInfoModel.setLastEventTime(time);
                    alarmInfoModel.setAlmstr(alarmDefModel.getAlmstr());
                    alarmInfoModel.setFval(actVal);
                    alarmInfoModel.setAlmCode(almCode);
                    alarmInfoModel.setSigname(signalName);
                    alarmInfoModel.setSigid(signalCode);
                    alarmInfoModel.setGatherid(gatherId);
                    alarmInfoModel.setSystemId(alarmDefModel.getAlmSystem());
                    alarmInfoModel.setAlarmCount("1");
                    alarmInfoModel.setAlmtypeid("3");
                    alarmInfoModel.setSystemName("");
                    alarmInfoModel.setAlmtypename("恢复报警");
                    alarmInfoModel.setAlarmStatus("1");
                    alarmInfoModel.setSendStatus("1");
                    alarmInfoModel.setAckFlag("0");
                    alarmInfoModel.setIsAnalysis("0");
                    alarmInfoModel.setShieldStatus("0");
                    alarmInfoModel.setIsShow("1");
                    alarmInfoModel.setDisposeStatus("0");
                    alarmInfoModel.setDalTime(time);
                    alarmInfoModel.setLastDalTime(time);
                    alarmInfoModel.setSpaceid(deviceDefModel.getSpaceid());
                    alarmInfoModel.setSpecilty(valunit);
                }

                this.judgeSave(alarmInfoModel);



                //---------------------------------固定时间段存储es数据-----------------------
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
                String saveStartTimeStr = "06:00:00";
                String saveEndTimeStr = "06:00:11";

                LocalTime saveStartTime = LocalTime.parse(saveStartTimeStr, formatter);
                LocalTime saveEndTime = LocalTime.parse(saveEndTimeStr, formatter);
                LocalTime nowTime=LocalTime.now();

                if(nowTime.isAfter(saveStartTime) & nowTime.isBefore(saveEndTime)){
                    saveToEs(time,signalCode,actVal,valunit,deviceDefModel);
                    return;
                }
                //------------------------------------------------------------------------

                if("1".equals(isSaveEs)){
                    saveToEs(time,signalCode,actVal,valunit,deviceDefModel);
                }
            }
        }
    }


    /**
     * 存储ES
     * @param time
     * @param signalCode
     * @param actVal
     * @param deviceDefModel
     */
    public void saveToEs(String time,String signalCode,String actVal,String valunit ,DeviceDefModel deviceDefModel){
        String uuid = UUID.randomUUID().toString(); //转化为String对象


        EsInfoModel currentEsModel=new EsInfoModel();
        currentEsModel.setId(uuid.replace("-", ""));
        currentEsModel.setTime(ThreadLocalDateUtil.parse(time).getTime());
        currentEsModel.setSignalCode(signalCode);
        currentEsModel.setValue(actVal);
        currentEsModel.setDevCode(deviceDefModel.getDevcode());
        currentEsModel.setDevTypeId(deviceDefModel.getDevtypeid());
        currentEsModel.setSpaceid(deviceDefModel.getSpaceid());
        currentEsModel.setSystemId(deviceDefModel.getSystemid());
        currentEsModel.setValunit(valunit);

        esInfoRepository.save(currentEsModel);
    }

    public  String getSeq() {

        String currentDate = DateUtil.getDate("yyyyMMdd");
        Long num = cacheService.getIncrementNum("demo_get_the_new_" + "test3_"+currentDate);
        String flowCode = currentDate+SequenceUtils.getSequence(num);
     //   System.out.println("流水号: " + flowCode);
        return flowCode;
    }
}
